home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / glibc108.gz / glibc108 / glibc-1.08.1 / sysdeps / m68k / fpu / switch / switch.c < prev   
C/C++ Source or Header  |  1992-05-01  |  3KB  |  87 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <signal.h>
  21. #include <68881-sw.h>
  22.  
  23.  
  24. /* The signal that is sent when a 68881 instruction
  25.    is executed and there is no 68881.  */
  26. #ifndef    TRAPSIG
  27. #define    TRAPSIG    SIGILL
  28. #endif
  29.  
  30. /* Zero if no 68881, one if we have a 68881, or -1 if we don't know yet.  */
  31. static int have_fpu = -1;
  32.  
  33.  
  34. /* Signal handler for the trap that happens if we don't have a 68881.  */
  35. static void
  36. DEFUN(trap, (sig), int sig)
  37. {
  38.   have_fpu = 0;
  39. }
  40.  
  41. /* This function is called by functions that want to switch.
  42.    The calling function must be a `struct switch_caller' in data space.
  43.    It determines whether a 68881 is present, and modifies its caller
  44.    to be a static jump to either the 68881 version or the soft version.
  45.    It then returns into the function it has chosen to do the work.  */
  46. void
  47. DEFUN(__68881_switch, (dummy), int dummy)
  48. {
  49.   PTR *return_address_location = &((PTR *) &dummy)[-1];
  50.   struct switch_caller *CONST caller
  51.     = (struct switch_caller *) (((short int *) *return_address_location) - 1);
  52.  
  53.   if (have_fpu < 0)
  54.     {
  55.       /* Figure out whether or not we have a 68881.  */
  56.       __sighandler_t handler = signal (TRAPSIG, trap);
  57.       if (handler == SIG_ERR)
  58.     /* We can't figure it out, so assume we don't have a 68881.
  59.        This assumption will never cause us any problems other than
  60.        lost performance, while the reverse assumption could cause
  61.        the program to crash.  */
  62.     have_fpu = 0;
  63.       else
  64.     {
  65.       /* We set `have_fpu' to nonzero, and then execute a 68881
  66.          no-op instruction.  If we have a 68881, this will do nothing.
  67.          If we don't have one, this will trap and the signal handler
  68.          will clear `have_fpu'.  */
  69.       have_fpu = 1;
  70.       asm ("fnop");
  71.  
  72.       /* Restore the old signal handler.  */
  73.       (void) signal (TRAPSIG, handler);
  74.     }
  75.     }
  76.  
  77.   /* Modify the caller to be a jump to the appropriate address.  */
  78.   caller->insn = JMP;
  79.   caller->target = have_fpu ? caller->fpu : caller->soft;
  80.  
  81.   /* Make the address we will return to be the target we have chosen.
  82.      Our return will match the `jsr' done by the caller we have
  83.      just modified, and it will be just as if that had instead
  84.      been a `jmp' to the new target.  */
  85.   *return_address_location = caller->target;
  86. }
  87.